import {
    _decorator,
    CCFloat,
    clamp,
    Component,
    find,
    Layout,
    Node,
    Prefab,
    Sprite,
    SpriteFrame,
    tween,
    UITransform,
    Vec3
} from "cc";
import {PriorityEnum} from "db://assets/scripts/game/PriorityEnum";
import {GameManager} from "db://assets/scripts/game/GameManager";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {PlayerController} from "db://assets/scripts/game/role/player/PlayerController";

const {ccclass, property} = _decorator;

/**
 * 玩家血条控制器
 */
@ccclass('PlayerBloodBarController')
export class PlayerBloodBarController extends Component {
    /**
     * 中间线的宽度
     */
    @property(CCFloat)
    public lineWidth: number = 1;
    /**
     * 中间线预制体
     */
    @property(Prefab)
    public linePrefab: Prefab;
    /**
     * 血块容器
     */
    @property(Node)
    public containerNode: Node;
    /**
     * container节点的layout组件
     */
    @property(Layout)
    public containerLayout: Layout;
    /**
     * 白色进度条的UI组件
     */
    @property(UITransform)
    public whiteBarTF: UITransform;
    /**
     * 白色进度条节点
     */
    @property(Node)
    public whiteBarNode: Node;
    /**
     * 血量进度条的UI组件
     */
    @property(UITransform)
    public currentBloodBarTF: UITransform;
    /**
     * 血量进度条节点
     */
    @property(Node)
    public currentBloodBarNode: Node;
    /**
     * 血条背景色
     */
    @property(Sprite)
    public bloodBarSP: Sprite;
    /**
     * 小怪和bos是红色背景
     */
    @property(SpriteFrame)
    public redSP: SpriteFrame;
    /**
     * 玩家是绿色背景
     */
    @property(SpriteFrame)
    public greenSP: SpriteFrame;
    /**
     * 血条容器节点
     */
    @property(UITransform)
    public bloodBarTF: UITransform;

    /**
     * 当前血量值
     */
    public currentBlood: number = 0;

    /**
     * 最小整体血条宽度
     */
    private minBloodBarWidth: number = 100;
    /**
     * 当前整体血条宽度
     */
    private bloodBarWidth: number = 0;
    /**
     * 最小单个血块宽度
     */
    private minBloodBarItemWidth: number = 10;
    /**
     * 每格血条
     */
    private maxItemBlood: number = 200;
    /**
     * 总的血量
     */
    private totalBlood: number = 0;
    /**
     * 跟随目标
     */
    private targetNode: Node;
    /**
     * 偏差
     */
    private offsetPosition: Vec3;
    /**
     * 当前血条位置
     */
    private currentPosition: Vec3;
    /**
     * 血条所在节点绑定的脚本
     */
    private scriptParent: PlayerController;
    /**
     * 血条缩放倍数
     */
    private scale: Vec3;
    /**
     * 血条高度
     */
    private bloodBarHeight: number = 15;
    /**
     * 初始线条容器节点位置
     */
    private originContainerPosition: Vec3 = new Vec3();
    /**
     * 当前线条容器节点位置
     */
    private currentContainerPosition: Vec3 = new Vec3();
    /**
     * 血条位置
     */
    private bloodBarPosition: Vec3 = new Vec3();
    /**
     * 白条位置
     */
    private whiteBarPosition: Vec3 = new Vec3();

    start() {

    }

    update(deltaTime: number) {
        if (this.node.parent && this.node.active && this.targetNode && this.targetNode.parent) {
            GameManager.getInstance().mainCamera.convertToUINode(this.targetNode.worldPosition, find("Canvas"), this.currentPosition);
            this.currentPosition.add(this.offsetPosition);
            this.node.setPosition(this.currentPosition);
        }
    }

    /**
     * 展示血条
     *
     * @param scriptParent 血条使用者绑定的节点，如玩家或者小怪
     * @param totalBlood 总血量
     * @param currentBlood 当前血量
     * @param offsetPosition 血条位置偏差
     * @param scale 血条缩放大小
     * @param callback 回调
     */
    public show(scriptParent: PlayerController,
                totalBlood: number,
                currentBlood: number,
                offsetPosition: Vec3,
                scale: Vec3,
                callback?: Function) {
        this.scriptParent = scriptParent;
        this.totalBlood = totalBlood;
        this.currentBlood = currentBlood;
        this.offsetPosition = offsetPosition;
        this.scale = scale;

        // 血块数量 = 总血量 / 每个血块显示的量
        let bloodItemNumber = Math.ceil(totalBlood / this.maxItemBlood);
        // 当前血条最小长度
        this.minBloodBarWidth = this.minBloodBarItemWidth * bloodItemNumber;
        // 所需血条总宽度大于最小整体血条宽度，需增大血条大小，反之使用最小血条宽度
        let isOutOfRange = this.bloodBarWidth > this.minBloodBarWidth;

        // 记录初始血块容器的位置
        this.originContainerPosition.set(this.containerNode.position);

        if (isOutOfRange) {
            this.currentContainerPosition.set(-this.bloodBarWidth * 0.5, this.originContainerPosition.y, 0);
            this.containerNode.setPosition(this.currentContainerPosition);
        } else {
            this.bloodBarWidth = this.minBloodBarWidth;
        }

        // 每个间隔线之间的距离，1为它本身的宽度，默认前后不显示
        this.containerLayout.spacingX = this.bloodBarWidth / bloodItemNumber - 1;

        // 隐藏容器里所有子节点
        for (let item of this.containerNode.children) {
            item.active = false;
        }

        // 当前血量占全部的比例
        let ratio = this.currentBlood / this.totalBlood;
        ratio = clamp(ratio, 0, 1);

        // 设置整体大小
        this.bloodBarTF.setContentSize(this.bloodBarWidth + 2, this.bloodBarHeight)
        // 设置界面优先级
        this.node.setSiblingIndex(PriorityEnum.ZERO);

        // 根据当前血量刷新中间连接线
        for (let i = 0; i < bloodItemNumber; i++) {
            let lineItemNode: Node;

            if (i >= this.containerNode.children.length) {
                lineItemNode = PoolManager.getInstance().getNode(this.linePrefab, this.containerNode);
            } else {
                lineItemNode = this.containerNode.children[i];
            }
            // 激活节点
            lineItemNode.active = true;

            let transform = lineItemNode.getComponent(UITransform);
            if (i % 5 === 0) {
                transform.setContentSize(1.5, 7);
            } else {
                transform.setContentSize(1, 5);
            }
        }

        let containerLayout = this.containerNode.getComponent(Layout);
        // 更新布局
        containerLayout.updateLayout();

        this.containerNode.children.forEach((child: Node, i: number) => {
            let childSprite = child.getComponent(Sprite);
            if (i === 0 || i === bloodItemNumber || child.position.x > this.bloodBarWidth * ratio) {
                childSprite.enabled = false;
            } else {
                childSprite.enabled = true;
            }
        });

        // 设置白色进度条长度和位置
        this.whiteBarTF.setContentSize(ratio * this.bloodBarWidth, this.bloodBarHeight * 0.8);
        this.whiteBarPosition.set(this.containerNode.position.x, 0.5, this.containerNode.position.z);
        this.whiteBarNode.setPosition(this.whiteBarPosition);

        // 设置血量进度条长度和位置
        this.currentBloodBarTF.setContentSize(ratio * this.bloodBarWidth, this.bloodBarHeight * 0.8);
        this.bloodBarPosition.set(this.containerNode.position.x, 0, this.containerNode.position.z);
        this.currentBloodBarNode.setPosition(this.bloodBarPosition);

        callback && callback();
    }

    /**
     * 刷新血量
     *
     * @param blood 血量
     * @param isIncreaseLimit 是否增加上限
     */
    public refreshBlood(blood: number, isIncreaseLimit: boolean = false) {
        this.currentBlood += blood;
        this.currentBlood = clamp(this.currentBlood, 0, this.totalBlood);
        let ratio = this.currentBlood / this.totalBlood;

        // 减血
        if (blood < 0) {
            ratio = ratio <= 0 ? 0 : ratio;

            this.currentBloodBarTF.setContentSize(this.bloodBarWidth * ratio, this.bloodBarHeight * 0.8);

            if (ratio > 0) {
                this.containerNode.children.forEach((child: Node) => {
                    let childSprite = child.getComponent(Sprite);
                    if (childSprite.enabled && child.position.x > this.bloodBarWidth * ratio) {
                        childSprite.enabled = false;
                    }
                });

                tween(this.whiteBarTF)
                    .to(0.7, {width: this.bloodBarWidth * blood})
                    .start();
            } else {
                this.node.active = false;
                // 玩家死亡
                this.scriptParent.setIsDie(true);
                this.currentBlood = 0;
            }
        } else {
            // 加血
            // 增加上限，并增加多出来的血量，最多不超过上限
            if (isIncreaseLimit) {
                this.currentBlood += blood;
                this.totalBlood += blood;
                this.currentBlood = this.currentBlood >= this.totalBlood ? this.totalBlood : this.currentBlood;
                ratio = this.currentBlood / this.totalBlood;
            } else {
                // 普通加血，最多不超过上限
                ratio = ratio >= 1 ? 1 : ratio;
            }

            tween(this.currentBloodBarTF)
                .to(1, {width: this.bloodBarWidth * ratio})
                .call(() => {
                    this.show(this.scriptParent, this.totalBlood, this.currentBlood, this.offsetPosition, this.scale);
                })
                .start();
        }
    }

    /**
     * 设置总血量
     *
     * @param totalBlood 总血量
     */
    public setTotalBlood(totalBlood: number) {
        this.totalBlood = totalBlood;
    }
}

